#include <QtNetwork>

#include "network.h"
#include "connection.h"
#include "peermanager.h"
#include <QDebug>

static const qint32 BROADCASTINTERVAL = 6000; // increase time
static const unsigned BROADCASTPORT = 45000;

PeerManager::PeerManager(Network *client)
    : QObject(client)
{
    this->m_network = client;

    serverPort = 0;

    broadcastSocket.bind(QHostAddress::Any, BROADCASTPORT, QUdpSocket::ShareAddress
                         | QUdpSocket::ReuseAddressHint);

    connect(&broadcastSocket, SIGNAL(readyRead()), this, SLOT(readBroadcastDatagram()));

    broadcastTimer.setInterval(BROADCASTINTERVAL);
    connect(&broadcastTimer, SIGNAL(timeout()), this, SLOT(sendBroadcastDatagram()));
}

void PeerManager::startBroadcasting()
{
    broadcastTimer.start();
}

void PeerManager::setServerPort(int port)
{
    serverPort = port;
}

bool PeerManager::isLocalHostAddress(const QHostAddress &address)
{
    foreach (QHostAddress localAddress, ipAddresses) {
        if (address.toIPv4Address() == localAddress.toIPv4Address())
            return true;
    }
    return false;
}

void PeerManager::sendBroadcastDatagram()
{
    QByteArray datagram("#coming");

    qint64 wr = broadcastSocket.writeDatagram(datagram, QHostAddress::Broadcast,
                                      BROADCASTPORT);
    qInfo() << "#write:" << datagram.size() << " real：" << wr;
}

void PeerManager::readBroadcastDatagram()
{
    while (broadcastSocket.hasPendingDatagrams()) {
        QHostAddress senderIp;
        quint16 senderPort;
        QByteArray datagram;

        datagram.resize(broadcastSocket.pendingDatagramSize());
        if (broadcastSocket.readDatagram(datagram.data(), datagram.size(),
                                         &senderIp, &senderPort) == -1)
            continue;

        qInfo() << "#info:" << senderIp << datagram;

        if (!datagram.startsWith("#"))
            continue;

        if (datagram.startsWith("#*")) {
            qInfo() << "#info key: " << datagram.remove(0, 2);
            emit shopDetection(QString(datagram.remove(0, 2)));
            return;
        }
        else if (datagram.startsWith("#leave")) {
            emit leave(senderIp.toString());
            return;
        }
        else if (datagram.startsWith("#coming")) {
            if (isLocalHostAddress(senderIp))
                return;

            if (broadcastAddresses.contains(senderIp)) {
                return;
            }

            emit newConnection(senderIp.toString());

            broadcastAddresses.append(senderIp);
        }
    }
}

//void PeerManager::updateAddresses()
//{
//    broadcastAddresses.clear();
//    ipAddresses.clear();
//    foreach (QNetworkInterface interface, QNetworkInterface::allInterfaces()) {
//        foreach (QNetworkAddressEntry entry, interface.addressEntries()) {
//            QHostAddress broadcastAddress = entry.broadcast();
//            if (broadcastAddress != QHostAddress::Null && entry.ip() != QHostAddress::LocalHost) {
//                broadcastAddresses << broadcastAddress;
//                ipAddresses << entry.ip();
//            }
//        }
//    }
//}
